home *** CD-ROM | disk | FTP | other *** search
- ############################################################################
- #
- # Name: recgen.icn
- #
- # Title: Generate recognizer for sentences in a context-free language
- #
- # Author: Ralph E. Griswold
- #
- # Date: June 10, 1988
- #
- ############################################################################
- #
- # This program reads a context-free grammar and produces an Icon
- # program that is a recognizer for the corresponding language.
- #
- # Nonterminal symbols are represented by uppercase letters. Vertical
- # bars separate alternatives. All other characters are considered to
- # be terminal symbols. The nonterminal symbol on the last line is
- # taken to be the goal.
- #
- # An example is:
- #
- # X::=T|T+X
- # T::=E|E*T
- # E::=x|y|z|(X)
- #
- # Limitations:
- #
- # Left recursion in the grammar may cause the recognizer to loop.
- # There is no check that all nonterminal symbols that are referenced
- # are defined.
- #
- # Reference:
- #
- # The Icon Programming Language, Ralph E. and Madge T. Griswold,
- # Prentice-Hall, 1983. pp. 161-165.
- #
- ############################################################################
-
- global goal
-
- procedure main()
- local line, sym
-
- while line := read() do define(line)
- write("\nprocedure main()")
- write(" while line := read() do {")
- write(" writes(image(line))")
- write(" if line ? (",goal,"() & pos(0)) then _
- write(\": accepted\")\n else write(\": rejected\")")
- write(" }")
- write("end")
- end
-
- procedure expand(s,x)
- local s1, sym
-
- s1 := ""
- s ? while sym := move(1) do
- if any(&ucase,sym) then s1 ||:= sym || "() || "
- else s1 ||:= "=\"" || sym || "\" || "
- return s1[1:-4]
- end
-
- procedure define(line)
- line ? (
- write("\nprocedure ",goal := move(1),"()"),
- ="::=",
- write(" suspend {"),
- (every write(" ",prodlist())) | "",
- write(" }"),
- write("end")
- )
- end
-
- procedure prodlist()
- local p
- while p := expand(tab(many(~'|')),"=") do {
- move(1) | return "(" || p || ")" # last alternative
- suspend "(" || p || ") |"
- }
- end
-
-